% Назначение: Расчет сигнальных точек модуляции
% Вход: name - название модуляции
%       q    - объем сигнального алфавита
%       E    - средняя энергия сигнала
% Выход: signals - множество сигнальных точек модуляции
% Обращение: signals = modulationSignals( name, q, E )
function [signals, d] = modulationSignals( name, q, E )
switch name
    case 'QAM'
        m = log2(q); % число бит переносимых сигналом
        
        if mod(m, 2) % если прореженное сигнальное множество
            sqrtQDown = sqrt(q / 2.0);
            sqrtQ     = sqrt(q * 2.0);
            
            l = sqrt( (6.0 * E) / (2.0*q - 1) ); % расстояние между
                                                 % сигнальными точками
            
            d = sqrt(2.0) * l; % минимальное расстояние между 
                               % сигнальными точками
        else         % если цельное сигнальное множество
            sqrtQ = sqrt(q);
            
            % E = ( (d^2) * (q - 1) ) / 6
            d = sqrt( (6.0 * E) / (q - 1) ); % минимальное расстояние между
                                             % сигнальными точками
            
            l = d;                           % расстояние между
                                             % сигнальными точками
        end
        
        A = ( l*( sqrtQ-1 ) ) / 2.0; % амплитуда
        
        i = 0 : q-1; % рассчитать все сигналы
        if mod(m, 2) % если прореженное сигнальное множество
            % i = i2*sqrtQDown + floor(i1/2);
            i2 = floor(i / sqrtQDown);
            i1 = 2*mod(i, sqrtQDown) + mod(i2, 2);
            % i1 = 2*mod(i, sqrtQDown) + ~mod(i2, 2);
        else         % если цельное сигнальное множество
            i2 = floor(i / sqrtQ); % целое от деления
            i1 = mod(i, sqrtQ);    % остаток от деления
        end
        
        % si1 и si2 лежат на отрезке [-A, A]
        si1 = A * ( (2*i1) / (sqrtQ-1) - 1 );
        si2 = A * ( (2*i2) / (sqrtQ-1) - 1 );
        
        signals = [si1; si2];
    case 'PSK'
        theta   = (2.0 * pi) / q;
        nums    = (0 : q-1);
        nums    = nums * theta;
        signals = [ sqrt(E) * cos(nums); sqrt(E) * sin(nums) ];
        d       = 2.0*sqrt(E) * sin( pi / q ); % минимальное расстояние 
                                               % между сигнальными точками
    otherwise
        disp('error: неизвестный тип модуляции. Известны "QAM" и "PSK"');
end
end
